package com.naiterui.ehp.ps.schedule.controller;

import com.naiterui.ehp.bp.constants.SwaggerTag;
import com.naiterui.ehp.bp.support.exception.PublicService;
import com.naiterui.ehp.bp.support.exception.ResponseVO;
import com.naiterui.ehp.bp.support.utils.JsonMapper;
import com.naiterui.ehp.ps.schedule.exception.ExceptionCodes;
import com.naiterui.ehp.ps.schedule.service.IScheduleJobService;
import com.naiterui.ehp.ps.schedule.utils.ScheduleCommon;
import com.naiterui.ehp.ps.schedule.vo.ScheduleJobVO;
import io.swagger.annotations.Api;
import org.apache.commons.lang3.StringUtils;
import org.quartz.SchedulerException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.io.IOException;
import java.util.List;
import java.util.Map;

/**
 * 任务调度controller
 *
 * @since HZD-1.0.0
 */
@Validated
@RestController
@RequestMapping("schedule")
@Api(tags = SwaggerTag.SCHEDULE + SwaggerTag.SCHEDULE_TASK)
public class ScheduleController {

    /**
     * 日志对象：<code>LOGGER</code>
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(ScheduleController.class);

    @Autowired
    private IScheduleJobService scheduleService;

    /**
     * 添加调度任务
     * ScheduleController.addSchedule()
     *
     * @param invokeTime 调度时间
     * @param timeStamp  时间戳
     * @param callBack   回调url
     * @param paramJson  回调参数json
     *
     * @return
     *
     * @Author Gaoll
     * @Date 2016年7月25日
     * @since HZD-1.0.0
     */
    @RequestMapping("/commonTask/add")
    public ResponseVO<String> addCommonTask(@NotEmpty(message = "调度时间不能为null") String invokeTime, @NotNull(message = "时间戳不能为null") Long timeStamp,
                                            @NotEmpty(message = "回调不能为null") String callBack, String paramJson) throws IOException,
            SchedulerException {
        LOGGER.info("添加调度任务 请求参数：invokeTime = {}, timeStamp = {}, callBack = {}, paramJson = {}", invokeTime, timeStamp, callBack, paramJson);

        ScheduleJobVO scheduleJobVO = new ScheduleJobVO();
        scheduleJobVO.setClassName(ScheduleCommon.COMMON_TASK);
        scheduleJobVO.setCronExpression(invokeTime);
        scheduleJobVO.setDescription("[通用任务] [开始]stamp:" + timeStamp);
        scheduleJobVO.setGroup(ScheduleCommon.COMMON_TASK_GROUP);
        scheduleJobVO.setName(ScheduleCommon.genCommonTaskName(timeStamp));
        scheduleJobVO.setStatus("1");
        scheduleJobVO.setUrl(callBack);
        if (StringUtils.isNotBlank(paramJson)) {
            Map<String, String> parameter = JsonMapper.toObject(paramJson, new ParameterizedTypeReference<Map<String, String>>() {
            });
            scheduleJobVO.setParameter(parameter);
        }

        this.scheduleService.add(scheduleJobVO);

        return PublicService.returnResponseVO(ScheduleCommon.genCommonTaskName(timeStamp));
    }

    /**
     * 取消定时任务
     * ScheduleController.cancelCommonTask()
     *
     * @param timeStamp 时间戳
     *
     * @return
     *
     * @Author Gaoll
     * @Date 2016年8月2日
     * @since HZD-1.0.0
     */
    @RequestMapping("/commonTask/cancel")
    public ResponseVO<Void> cancelCommonTask(@NotNull(message = "timeStamp 不能为null") Long timeStamp) throws SchedulerException {
        LOGGER.info("取消定时任务 请求参数：timeStamp = {}", timeStamp);

        String name = ScheduleCommon.genCommonTaskName(timeStamp);
        String group = ScheduleCommon.COMMON_TASK_GROUP;
        this.scheduleService.deleteJob(name, group);
        return PublicService.returnResponseVO(ExceptionCodes.SUCCESS);
    }

    /**
     * 添加调度任务
     * ScheduleController.addCustomerTask()
     *
     * @param invokeTime 调度时间
     * @param timeStamp  时间戳
     * @param callBack   回调url
     * @param paramJson  回调参数json
     *
     * @return
     *
     * @Author Gaoll
     * @Date 2016年7月25日
     * @since HZD-1.0.0
     */
    @RequestMapping("/customerTask/add")
    public ResponseVO<String> addCustomerTask(@NotEmpty(message = "调度时间不能为null") String invokeTime,
                                              @NotNull(message = "任务类型不能为null") Integer taskType,
                                              @NotEmpty(message = "unionId 不能为null") String unionId, @NotEmpty(message = "回调不能为null") String callBack,
                                              String paramJson) throws IOException, SchedulerException {
        LOGGER.info("添加调度任务 请求参数：invokeTime = {}, taskType = {}, unionId = {}, callBack = {}, paramJson = {}", invokeTime, taskType, unionId,
                    callBack, paramJson);

        ScheduleJobVO scheduleJobVO = new ScheduleJobVO();
        scheduleJobVO.setClassName(ScheduleCommon.COMMON_TASK);
        scheduleJobVO.setCronExpression(invokeTime);
        scheduleJobVO.setDescription("[自定义任务]" + "[开始]taskType:" + taskType + ",taskUnionId:" + unionId);
        scheduleJobVO.setGroup(ScheduleCommon.CUSTOMER_TASK_GROUP);
        scheduleJobVO.setName(ScheduleCommon.genCustomerTaskName(taskType, unionId));
        scheduleJobVO.setStatus("1");
        scheduleJobVO.setUrl(callBack);
        if (StringUtils.isNotBlank(paramJson)) {
            Map<String, String> parameter = JsonMapper.toObject(paramJson, new ParameterizedTypeReference<Map<String, String>>() {
            });
            scheduleJobVO.setParameter(parameter);
        }

        this.scheduleService.add(scheduleJobVO);

        return PublicService.returnResponseVO(ScheduleCommon.genCustomerTaskName(taskType, unionId));

    }

    @RequestMapping("/customerTask/cancel")
    public ResponseVO<Void> cancelCustomerTask(@NotNull(message = "taskType 不能为null") Integer taskType,
                                               @NotEmpty(message = "unionId 不能为null") String unionId) throws SchedulerException {
        LOGGER.info("取消任务 请求参数：taskType = {}, unionId = {}", taskType, unionId);

        String name = ScheduleCommon.genCustomerTaskName(taskType, unionId);
        String group = ScheduleCommon.CUSTOMER_TASK_GROUP;
        this.scheduleService.deleteJob(name, group);
        return PublicService.returnResponseVO(ExceptionCodes.SUCCESS);
    }

    @PostMapping("/add")
    public ResponseVO<Void> add(@RequestBody @Validated ScheduleJobVO scheduleJobVO) throws SchedulerException {
        LOGGER.info("添加任务 请求参数：scheduleJobVO = {}", scheduleJobVO);
        scheduleJobVO.setClassName(ScheduleCommon.COMMON_TASK);
        scheduleJobVO.setStatus("1");
        this.scheduleService.add(scheduleJobVO);
        return PublicService.returnResponseVO(ExceptionCodes.SUCCESS);
    }

    @PostMapping("/update")
    public ResponseVO<Void> update(@RequestBody @Validated ScheduleJobVO scheduleJobVO) throws SchedulerException {
        LOGGER.info("修改任务 请求参数：scheduleJobVO = {}", scheduleJobVO);
        scheduleJobVO.setClassName(ScheduleCommon.COMMON_TASK);
        scheduleJobVO.setStatus("1");
        this.scheduleService.update(scheduleJobVO);
        return PublicService.returnResponseVO(ExceptionCodes.SUCCESS);
    }

    /**
     * <pre>
     *     取消任务
     * </pre>
     *
     * @param name  任务名称
     * @param group 任务组
     *
     * @return
     *
     * @throws SchedulerException
     */
    @GetMapping("/cancel")
    public ResponseVO<Void> cancelJob(@NotEmpty(message = "任务名称不能为null") String name,
                                      @NotEmpty(message = "任务组不能为空") String group) throws SchedulerException {
        this.scheduleService.deleteJob(name, group);
        return PublicService.returnResponseVO(ExceptionCodes.SUCCESS);
    }

    /**
     * <pre>
     *     立即执行一次任务
     * </pre>
     *
     * @param name  任务名称
     * @param group 任务组
     *
     * @return
     *
     * @throws SchedulerException
     */
    @GetMapping("/start/one")
    public ResponseVO<Void> startNowJob(@NotEmpty(message = "任务名称不能为null") String name,
                                        @NotEmpty(message = "任务组不能为空") String group) throws SchedulerException {
        this.scheduleService.startNowJob(name, group);
        return PublicService.returnResponseVO(ExceptionCodes.SUCCESS);
    }

    /**
     * <pre>
     *     停止任务
     * </pre>
     *
     * @param name  任务名称
     * @param group 任务组
     *
     * @return
     *
     * @throws SchedulerException
     */
    @GetMapping("/stop")
    public ResponseVO<Void> stopJob(@NotEmpty(message = "任务名称不能为null") String name,
                                    @NotEmpty(message = "任务组不能为空") String group) throws SchedulerException {
        this.scheduleService.stopJob(name, group);
        return PublicService.returnResponseVO(ExceptionCodes.SUCCESS);
    }

    /**
     * <pre>
     *     恢复任务
     * </pre>
     *
     * @param name  任务名称
     * @param group 任务组
     *
     * @return
     *
     * @throws SchedulerException
     */
    @GetMapping("/restart")
    public ResponseVO<Void> restartJob(@NotEmpty(message = "任务名称不能为null") String name,
                                       @NotEmpty(message = "任务组不能为空") String group) throws SchedulerException {
        this.scheduleService.restartJob(name, group);
        return PublicService.returnResponseVO(ExceptionCodes.SUCCESS);
    }

    @PostMapping("job/list")
    public ResponseVO<List<ScheduleJobVO>> listSchedule() throws SchedulerException {
        List<ScheduleJobVO> jobs = this.scheduleService.getAllScheduleJob();
        return PublicService.returnResponseVO(jobs);
    }

}
